import * as THREE from 'three'
import type { Cabinet } from '@/stores/datacenter'
import { CabinetType } from '@/stores/datacenter'

export class CabinetMeshFactory {

    static createPillars(cabinet: Cabinet, material: THREE.Material): THREE.Mesh[] {
        const pillars: THREE.Mesh[] = []
        const pillarGeometry = new THREE.BoxGeometry(40, cabinet.height, 40) // 4cm x 4cm 立柱

        const positions = [
            [-cabinet.width / 2 + 20, 0, cabinet.depth / 2 - 20],  // 前左
            [cabinet.width / 2 - 20, 0, cabinet.depth / 2 - 20],   // 前右  
            [-cabinet.width / 2 + 20, 0, -cabinet.depth / 2 + 20], // 后左
            [cabinet.width / 2 - 20, 0, -cabinet.depth / 2 + 20]   // 后右
        ]

        positions.forEach(pos => {
            const pillar = new THREE.Mesh(pillarGeometry, material)
            pillar.position.set(pos[0], pos[1], pos[2])
            pillar.castShadow = true
            pillars.push(pillar)
        })

        return pillars
    }

    static createPanels(cabinet: Cabinet, material: THREE.Material): THREE.Mesh[] {
        const panels: THREE.Mesh[] = []

        // 左侧板
        const leftPanelGeometry = new THREE.BoxGeometry(20, cabinet.height - 100, cabinet.depth - 80)
        const leftPanel = new THREE.Mesh(leftPanelGeometry, material)
        leftPanel.position.set(-cabinet.width / 2 + 10, 0, 0)
        leftPanel.castShadow = true
        leftPanel.receiveShadow = true
        panels.push(leftPanel)

        // 右侧板
        const rightPanelGeometry = new THREE.BoxGeometry(20, cabinet.height - 100, cabinet.depth - 80)
        const rightPanel = new THREE.Mesh(rightPanelGeometry, material)
        rightPanel.position.set(cabinet.width / 2 - 10, 0, 0)
        rightPanel.castShadow = true
        rightPanel.receiveShadow = true
        panels.push(rightPanel)

        // 顶板
        const topPanelGeometry = new THREE.BoxGeometry(cabinet.width - 40, 20, cabinet.depth - 40)
        const topPanel = new THREE.Mesh(topPanelGeometry, material)
        topPanel.position.set(0, cabinet.height / 2 - 10, 0)
        topPanel.castShadow = true
        topPanel.receiveShadow = true
        panels.push(topPanel)

        // 底板
        const bottomPanelGeometry = new THREE.BoxGeometry(cabinet.width - 40, 20, cabinet.depth - 40)
        const bottomPanel = new THREE.Mesh(bottomPanelGeometry, material)
        bottomPanel.position.set(0, -cabinet.height / 2 + 10, 0)
        bottomPanel.castShadow = true
        bottomPanel.receiveShadow = true
        panels.push(bottomPanel)

        return panels
    }

    static createBeams(cabinet: Cabinet, material: THREE.Material): THREE.Mesh[] {
        const beams: THREE.Mesh[] = []
        const beamGeometry = new THREE.BoxGeometry(40, 40, cabinet.depth - 80)

        const beamPositions = [
            [-cabinet.width / 2 + 20, cabinet.height / 2 - 40, 0],  // 顶部左
            [cabinet.width / 2 - 20, cabinet.height / 2 - 40, 0],   // 顶部右
            [-cabinet.width / 2 + 20, -cabinet.height / 2 + 40, 0], // 底部左
            [cabinet.width / 2 - 20, -cabinet.height / 2 + 40, 0]   // 底部右
        ]

        beamPositions.forEach(pos => {
            const beam = new THREE.Mesh(beamGeometry, material)
            beam.position.set(pos[0], pos[1], pos[2])
            beam.castShadow = true
            beams.push(beam)
        })

        return beams
    }

    static createRails(cabinet: Cabinet, material: THREE.Material): THREE.Mesh[] {
        const rails: THREE.Mesh[] = []

        // 只有服务器机柜才有导轨
        if (cabinet.type !== CabinetType.SERVER) {
            return rails
        }

        const railGeometry = new THREE.BoxGeometry(20, cabinet.height - 200, 20)

        const railPositions = [
            [-cabinet.width / 2 + 60, 0, cabinet.depth / 2 - 60], // 左导轨
            [cabinet.width / 2 - 60, 0, cabinet.depth / 2 - 60]   // 右导轨
        ]

        railPositions.forEach(pos => {
            const rail = new THREE.Mesh(railGeometry, material)
            rail.position.set(pos[0], pos[1], pos[2])
            rail.castShadow = true
            rails.push(rail)
        })

        return rails
    }

    static createSpecialFeatures(cabinet: Cabinet): THREE.Mesh[] {
        const features: THREE.Mesh[] = []

        switch (cabinet.type) {
            case CabinetType.AC:
                // 创建前面板进风格栅
                const grilleMaterial = new THREE.MeshLambertMaterial({ color: 0x333333 })

                // 主进风格栅
                const mainGrilleGeometry = new THREE.BoxGeometry(cabinet.width - 100, cabinet.height - 300, 50)
                const mainGrille = new THREE.Mesh(mainGrilleGeometry, grilleMaterial)
                mainGrille.position.set(0, 0, cabinet.depth / 2 + 25)
                mainGrille.castShadow = true
                features.push(mainGrille)

                // 创建格栅孔洞效果（多个小孔）
                for (let y = -cabinet.height / 3; y < cabinet.height / 3; y += 100) {
                    for (let x = -cabinet.width / 3; x < cabinet.width / 3; x += 80) {
                        const holeGeometry = new THREE.BoxGeometry(60, 80, 60)
                        const holeMaterial = new THREE.MeshLambertMaterial({ color: 0x000000 })
                        const hole = new THREE.Mesh(holeGeometry, holeMaterial)
                        hole.position.set(x, y, cabinet.depth / 2 + 20)
                        features.push(hole)
                    }
                }

                // 顶部出风口
                const outletGeometry = new THREE.BoxGeometry(cabinet.width - 80, 100, cabinet.depth - 80)
                const outletMaterial = new THREE.MeshLambertMaterial({ color: 0x444444 })
                const outlet = new THREE.Mesh(outletGeometry, outletMaterial)
                outlet.position.set(0, cabinet.height / 2 + 50, 0)
                outlet.castShadow = true
                features.push(outlet)

                // 出风叶片
                for (let i = 0; i < 5; i++) {
                    const bladeGeometry = new THREE.BoxGeometry(cabinet.width - 120, 10, cabinet.depth - 120)
                    const bladeMaterial = new THREE.MeshLambertMaterial({ color: 0x666666 })
                    const blade = new THREE.Mesh(bladeGeometry, bladeMaterial)
                    blade.position.set(0, cabinet.height / 2 + 60 + i * 15, 0)
                    blade.castShadow = true
                    features.push(blade)
                }

                // 侧面冷凝器（假象的散热器）
                const condenserGeometry = new THREE.BoxGeometry(50, cabinet.height - 200, cabinet.depth - 200)
                const condenserMaterial = new THREE.MeshLambertMaterial({ color: 0x888888 })
                const condenser = new THREE.Mesh(condenserGeometry, condenserMaterial)
                condenser.position.set(-cabinet.width / 2 - 25, 0, 0)
                condenser.castShadow = true
                features.push(condenser)

                // 控制面板
                const controlPanelGeometry = new THREE.BoxGeometry(200, 150, 20)
                const controlPanelMaterial = new THREE.MeshLambertMaterial({ color: 0x222222 })
                const controlPanel = new THREE.Mesh(controlPanelGeometry, controlPanelMaterial)
                controlPanel.position.set(cabinet.width / 3, cabinet.height / 3, cabinet.depth / 2 + 10)
                controlPanel.castShadow = true
                features.push(controlPanel)

                // 控制面板指示灯
                const indicatorGeometry = new THREE.SphereGeometry(10, 8, 8)
                const greenLight = new THREE.Mesh(indicatorGeometry, new THREE.MeshLambertMaterial({
                    color: 0x00ff00,
                    emissive: 0x003300
                }))
                greenLight.position.set(cabinet.width / 3 - 50, cabinet.height / 3 + 50, cabinet.depth / 2 + 20)
                features.push(greenLight)

                const redLight = new THREE.Mesh(indicatorGeometry, new THREE.MeshLambertMaterial({
                    color: 0xff0000,
                    emissive: 0x330000
                }))
                redLight.position.set(cabinet.width / 3 + 50, cabinet.height / 3 + 50, cabinet.depth / 2 + 20)
                features.push(redLight)
                break

            case CabinetType.NETWORK:
                // 创建网络指示灯
                for (let i = 0; i < 3; i++) {
                    const lightGeometry = new THREE.SphereGeometry(20, 8, 8)
                    const lightMaterial = new THREE.MeshLambertMaterial({
                        color: i === 0 ? 0x00ff00 : (i === 1 ? 0xffff00 : 0xff0000),
                        emissive: i === 0 ? 0x002200 : (i === 1 ? 0x222200 : 0x220000)
                    })
                    const light = new THREE.Mesh(lightGeometry, lightMaterial)
                    light.position.set(-100 + i * 100, cabinet.height / 2 - 50, cabinet.depth / 2 + 10)
                    features.push(light)
                }
                break

            case CabinetType.POWER:
                // 创建配电指示器
                const meterGeometry = new THREE.BoxGeometry(200, 100, 50)
                const meterMaterial = new THREE.MeshLambertMaterial({ color: 0x000000 })
                const meter = new THREE.Mesh(meterGeometry, meterMaterial)
                meter.position.set(0, cabinet.height / 3, cabinet.depth / 2 + 25)
                meter.castShadow = true
                features.push(meter)
                break
        }

        return features
    }

    static createDevices(cabinet: Cabinet): THREE.Mesh[] {
        const devices: THREE.Mesh[] = []

        // 只有服务器机柜才显示设备
        if (cabinet.type !== CabinetType.SERVER || cabinet.devices.length === 0) {
            return devices
        }

        cabinet.devices.forEach(device => {
            // 设备尺寸计算
            const deviceWidth = cabinet.width - 120 // 比机柜内部窄一些
            const deviceHeight = device.rackUnits * 44.45 // 1U = 44.45mm 标准高度
            const deviceDepth = cabinet.depth - 200 // 比机柜内部浅一些

            // 设备材质
            let deviceColor = 0x333333 // 默认深灰色
            switch (device.type) {
                case 'server':
                    deviceColor = 0x4a90e2 // 蓝色
                    break
                case 'switch':
                    deviceColor = 0x50c878 // 绿色
                    break
                case 'router':
                    deviceColor = 0xff9500 // 橙色
                    break
                case 'storage':
                    deviceColor = 0x9b59b6 // 紫色
                    break
                case 'firewall':
                    deviceColor = 0xe74c3c // 红色
                    break
            }

            const deviceMaterial = new THREE.MeshLambertMaterial({
                color: deviceColor,
                emissive: deviceColor,
                emissiveIntensity: 0.1
            })

            // 创建设备主体
            const deviceGeometry = new THREE.BoxGeometry(deviceWidth, deviceHeight, deviceDepth)
            const deviceMesh = new THREE.Mesh(deviceGeometry, deviceMaterial)

            // 计算设备位置
            // U位置从底部开始，1U在最底部
            const rackPositionY = -cabinet.height / 2 + 50 + (device.rackPosition - 1) * 44.45 + deviceHeight / 2

            deviceMesh.position.set(0, rackPositionY, 0)
            deviceMesh.castShadow = true
            deviceMesh.receiveShadow = true

            // 为设备添加userData，用于识别
            deviceMesh.userData = {
                deviceId: device.id,
                cabinetId: cabinet.id,
                type: 'device'
            }

            // 添加设备前面板细节
            const frontPanelGeometry = new THREE.BoxGeometry(deviceWidth - 20, deviceHeight - 10, 10)
            const frontPanelMaterial = new THREE.MeshLambertMaterial({
                color: deviceColor,
                emissive: deviceColor,
                emissiveIntensity: 0.15
            })
            const frontPanel = new THREE.Mesh(frontPanelGeometry, frontPanelMaterial)
            frontPanel.position.set(0, rackPositionY, deviceDepth / 2 + 5)
            frontPanel.castShadow = true

            // 前面板也添加相同的userData
            frontPanel.userData = {
                deviceId: device.id,
                cabinetId: cabinet.id,
                type: 'device'
            }

            // 添加设备指示灯
            const indicatorGeometry = new THREE.SphereGeometry(3, 8, 8)

            // 电源指示灯 (绿色)
            const powerLight = new THREE.Mesh(indicatorGeometry, new THREE.MeshLambertMaterial({
                color: 0x00ff00,
                emissive: 0x004400,
                emissiveIntensity: 0.3
            }))
            powerLight.position.set(deviceWidth / 2 - 30, rackPositionY, deviceDepth / 2 + 10)

            // 活动指示灯 (蓝色)
            const activityLight = new THREE.Mesh(indicatorGeometry, new THREE.MeshLambertMaterial({
                color: 0x0088ff,
                emissive: 0x002244,
                emissiveIntensity: 0.3
            }))
            activityLight.position.set(deviceWidth / 2 - 50, rackPositionY, deviceDepth / 2 + 10)

            devices.push(deviceMesh, frontPanel, powerLight, activityLight)
        })

        return devices
    }

    static createMaterials(cabinet: Cabinet) {
        const frameMaterial = new THREE.MeshLambertMaterial({
            color: cabinet.color
        })

        const metalMaterial = new THREE.MeshLambertMaterial({
            color: 0x888888 // 金属灰色
        })

        return { frameMaterial, metalMaterial }
    }

    static create(cabinet: Cabinet): THREE.Group {
        const cabinetGroup = new THREE.Group()

        const { frameMaterial, metalMaterial } = this.createMaterials(cabinet)

        // 添加基础组件
        const pillars = this.createPillars(cabinet, metalMaterial)
        const panels = this.createPanels(cabinet, frameMaterial)
        const beams = this.createBeams(cabinet, metalMaterial)
        const rails = this.createRails(cabinet, metalMaterial)
        const specialFeatures = this.createSpecialFeatures(cabinet)
        const devices = this.createDevices(cabinet)

        // 将所有组件添加到组中
        pillars.forEach(pillar => cabinetGroup.add(pillar))
        panels.forEach(panel => cabinetGroup.add(panel))
        beams.forEach(beam => cabinetGroup.add(beam))
        rails.forEach(rail => cabinetGroup.add(rail))
        specialFeatures.forEach(feature => cabinetGroup.add(feature))
        devices.forEach(device => cabinetGroup.add(device))

        return cabinetGroup
    }
} 